package com.weilx959.spt.core.component;

import com.weilx959.spt.core.serialize.ValueDeserializer;
import com.weilx959.spt.core.serialize.ValueSerializer;

import java.util.Optional;

/**
 * {{@link ParentFormItemControl}} builder
 * 
 * @param <T> the type of value
 * @param <S> the type of {@link ParentFormItemControl}
 * @param <R> the type of {@link ParentFormItemControlBuilder}
 * @author weilx 
 * @since 2024年6月9日
 */
public abstract class ParentFormItemControlBuilder<T, S extends ParentFormItemControl<T>, R extends ParentFormItemControlBuilder<T, S, R>> {
    protected String label;
    protected String key;
    protected T value;
    protected boolean editable = true;
    protected ValueSerializer<T> serializer;
    protected ValueDeserializer<T> deserializer;
    protected int colspan;
    protected int rowspan;

    public R label(String label) {
        this.label = label;
        return self();
    }

    public R key(String key) {
        this.key = key;
        return self();
    }

    public R value(T value) {
        this.value = value;
        return self();
    }

    public R editable(boolean editable) {
        this.editable = editable;
        return self();
    }

    public R serializer(ValueSerializer<T> serializer) {
        this.serializer = serializer;
        return self();
    }

    public R deserializer(ValueDeserializer<T> deserializer) {
        this.deserializer = deserializer;
        return self();
    }

    public R colspan(int colspan) {
        this.colspan = colspan;
        return self();
    }

    public R rowspan(int rowspan) {
        this.rowspan = rowspan;
        return self();
    }

    public S build() {
        S control = newFormItemControl();
        control.setLabel(label);
        control.setKey(key);
        control.setOldValue(value);
        control.setValue(value);
        control.setEditable(editable);
        Optional.ofNullable(serializer).ifPresent(control::setSerializer);
        Optional.ofNullable(deserializer).ifPresent(control::setDeserializer);
        control.setColspan(colspan);
        control.setRowspan(rowspan);
        return control;
    }

    protected abstract S newFormItemControl();
    
    protected abstract R self();
}
